home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
grep.zip
/
GREP.C
< prev
next >
Wrap
Text File
|
1993-01-04
|
14KB
|
565 lines
#include <stdio.h>
#include <ctype.h>
#include <dos.h>
#include <dir.h>
#include <process.h>
#include <string.h>
#include <mem.h>
#include <errno.h>
#include "grep.h"
main(argc, argv)
char *argv[];
{
char *p;
register int i;
register char c;
int gotpattern;
int count, start;
FILE *f;
char *fname;
if (argc <= 1)
usage("No arguments");
if (argc == 2 && argv[1][0] == '?' && argv[1][1] == 0) {
help(documentation);
help(patdoc);
return;
}
nfile = argc-1;
gotpattern = 0;
for (i=1; i < argc; ++i) {
p = argv[i];
if (*p == '-') {
++p;
while ( (c = *p++) != 0)
{
switch(tolower(c)) {
case '?':
help(documentation);
break;
case 'C':
case 'c':
++cflag;
break;
case 'D':
case 'd':
++debug;
break;
case 'F':
case 'f':
++fflag;
break;
case 'n':
case 'N':
++nflag;
break;
case 'v':
case 'V':
++vflag;
break;
default:
usage("Unknown flag");
}
}
argv[i] = 0;
--nfile;
} else if (!gotpattern) {
compile(p);
argv[i] = 0;
++gotpattern;
--nfile;
}
}
if (!gotpattern)
usage("No pattern");
if (nfile == 0)
grep(stdin, 0);
else
{
fflag = fflag ^ (nfile > 0);
for (i=1; i < argc; ++i)
{
if ( (p = argv[i]) != 0)
{
count = getfnl(p,fnames,FNASIZE,6);
if (count > 0)
{
if (strbpl(fpointers, MAXFILES, fnames) != count)
toomany(p);
else
{
start = 0;
while ( (fname = fpointers[start++]) != 0)
{
if ((f=fopen(fname, "r")) == NULL)
cant(fname);
else
{
grep(f, fname);
fclose(f);
}
}
}
}
else
{
if (errno == ENOMEM)
toomany(p);
else
cant(p);
}
}
}
}
}
/*******************************************************/
void file(s)
char *s;
{
if (lfeed++)
printf("\n");
printf("File %s:\n", s);
}
/*******************************************************/
void toomany(s)
char *s;
{
strupr(s);
fprintf(stderr,"\nGREP: too many file names - %s\n", s);
}
void cant(s)
char *s;
{
strupr(s);
fprintf(stderr, "\nGREP: bad path name or file not found - %s\n", s);
}
/*******************************************************/
void help(hp)
char **hp; /* dns added extra '*' */
/*
* Give good help
*/
{
register char **dp;
for (dp = hp; *dp; dp++)
printf("%s\n", *dp);
}
/*******************************************************/
void usage(s)
char *s;
{
fprintf(stderr, "GREP: %s\n", s);
fprintf(stderr,
"Usage: grep [-cfnv] pattern [file ...]. grep ? for help\n");
exit(1);
}
/*******************************************************/
void compile(source)
char *source; /* Pattern to compile */
/*
* Compile the pattern into global pbuf[]
*/
{
char *s; /* Source string pointer */
char *lp; /* Last pattern pointer */
register char c; /* Current character */
int o; /* Temp */
char *spp; /* Save beginning of pattern */
char *cclass(); /* Compile class routine */
s = source;
lp = NULL;
if (debug)
printf("Pattern = \"%s\"\n", s);
pp = pbuf;
while ( (c = *s++) != 0)
{
/*
* STAR, PLUS and MINUS are special.
*/
if (c == '*' || c == '+' || c == '-') {
if (pp == pbuf ||
(o=pp[-1]) == BOL ||
o == EOL ||
o == STAR ||
o == PLUS ||
o == MINUS)
badpat("Illegal occurrance op.", source, s);
store(ENDPAT);
store(ENDPAT);
spp = pp; /* Save pattern end */
while (--pp > lp) /* Move pattern down */
*pp = pp[-1]; /* one byte */
*pp = (c == '*') ? STAR :
(c == '-') ? MINUS : PLUS;
pp = spp; /* Restore pattern end */
continue;
}
/*
* All the rest.
*/
lp = pp; /* Remember start */
switch(c) {
case '^':
store(BOL);
break;
case '$':
store(EOL);
break;
case '.':
store(ANY);
break;
case '[':
s = cclass(source, s);
break;
case ':':
if (*s) {
c = *s++;
switch(tolower(c)) {
case 'a':
case 'A':
store(ALPHA);
break;
case 'd':
case 'D':
store(DIGIT);
break;
case 'n':
case 'N':
store(NALPHA);
break;
case ' ':
store(PUNCT);
break;
default:
badpat("Unknown : type", source, s);
}
break;
}
else badpat("No : type", source, s);
case '\\':
if (*s)
c = *s++;
default:
store(CHAR);
store(tolower(c));
}
}
store(ENDPAT);
store(0); /* Terminate string */
if (debug) {
for (lp = pbuf; lp < pp;) {
if ((c = (*lp++ & 0377)) < ' ')
printf("\\%o ", c);
else printf("%c ", c);
}
printf("\n");
}
}
/*******************************************************/
char *
cclass(source, src)
char *source; /* Pattern start -- for error msg. */
char *src; /* Class start */
/*
* Compile a class (within [])
*/
{
register char *s; /* Source pointer */
register char *cp; /* Pattern start */
register int c; /* Current character */
int o; /* Temp */
s = src;
o = CLASS;
if (*s == '^') {
++s;
o = NCLASS;
}
store(o);
cp = pp;
store(0); /* Byte count */
while ( ((c = *s++) != 0) && c != ']')
{
if (c == '\\') { /* Store quoted char */
if ((c = *s++) == '\0') /* Gotta get something */
badpat("Class terminates badly", source, s);
else store(tolower(c));
}
else if (c == '-' &&
(pp - cp) > 1 && *s != ']' && *s != '\0') {
c = pp[-1]; /* Range start */
pp[-1] = RANGE; /* Range signal */
store(c); /* Re-store start */
c = *s++; /* Get end char and*/
store(tolower(c)); /* Store it */
}
else {
store(tolower(c)); /* Store normal char */
}
}
if (c != ']')
badpat("Unterminated class", source, s);
if ((c = (pp - cp)) >= 256)
badpat("Class too large", source, s);
if (c == 0)
badpat("Empty class", source, s);
*cp = c;
return(s);
}
/*******************************************************/
void store(op)
char op;
{
if (pp >= &pbuf[PMAX])
error("Pattern too complex\n");
*pp++ = op;
}
/*******************************************************/
void badpat(message, source, stop)
char *message; /* Error message */
char *source; /* Pattern start */
char *stop; /* Pattern end */
{
fprintf(stderr, "GREP: %s, pattern is\"%s\"\n", message, source);
fprintf(stderr, "GREP: Stopped at byte %d, character '%c'\n",
stop-source, stop[-1]);
error("GREP: Bad pattern\n");
}
/*******************************************************/
void grep(fp, fn)
FILE *fp; /* File to process */
char *fn; /* File name (for -f option) */
/*
* Scan the file for the pattern in pbuf[]
*/
{
register int lno, count, m;
lno = 0;
count = 0;
while (fgets(lbuf, LMAX, fp)) {
++lno;
m = match();
if ((m && !vflag) || (!m && vflag)) {
++count;
if (!cflag) {
if (fflag && fn) {
file(fn);
fn = 0;
}
if (nflag)
printf("%d\t", lno);
printf("%s", lbuf);
/*printf("%s\n", lbuf);*/
}
}
}
if (cflag) {
if (fflag && fn)
file(fn);
printf("%d\n", count);
}
}
/*******************************************************/
int match()
/*
* Match the current line (in lbuf[]), return 1 if it does.
*/
{
register char *l; /* Line pointer */
char *pmatch();
for (l = lbuf; *l; l++) {
if (pmatch(l, pbuf))
return(1);
}
return(0);
}
/*******************************************************/
char *
pmatch(line, pattern)
char *line; /* (partial) line to match */
char *pattern; /* (partial) pattern to match */
{
register char *l; /* Current line pointer */
register char *p; /* Current pattern pointer */
register char c; /* Current character */
char *e; /* End for STAR and PLUS match */
int op; /* Pattern operation */
int n; /* Class counter */
char *are; /* Start of STAR match */
l = line;
if (debug > 1)
printf("pmatch(\"%s\")\n", line);
p = pattern;
while ((op = *p++) != ENDPAT) {
if (debug > 1)
printf("byte[%d] = 0%o, '%c', op = 0%o\n",
l-line, *l, *l, op);
switch(op) {
case CHAR:
if (tolower(*l++) != *p++)
return(0);
break;
case BOL:
if (l != lbuf)
return(0);
break;
case EOL:
if (*l != '\0')
return(0);
break;
case ANY:
if (*l++ == '\0')
return(0);
break;
case DIGIT:
if ((c = *l++) < '0' || (c > '9'))
return(0);
break;
case ALPHA:
c = tolower(*l++);
if (c < 'a' || c > 'z')
return(0);
break;
case NALPHA:
c = tolower(*l++);
if (c >= 'a' && c <= 'z')
break;
else if (c < '0' || c > '9')
return(0);
break;
case PUNCT:
c = *l++;
if (c == 0 || c > ' ')
return(0);
break;
case CLASS:
case NCLASS:
c = tolower(*l++);
n = *p++ & 0377;
do {
if (*p == RANGE) {
p += 3;
n -= 2;
if (c >= p[-2] && c <= p[-1])
break;
}
else if (c == *p++)
break;
} while (--n > 1);
if ((op == CLASS) == (n <= 1))
return(0);
if (op == CLASS)
p += n - 2;
break;
case MINUS:
e = pmatch(l, p); /* Look for a match */
while (*p++ != ENDPAT); /* Skip over pattern */
if (e) /* Got a match? */
l = e; /* Yes, update string */
break; /* Always succeeds */
case PLUS: /* One or more ... */
if ((l = pmatch(l, p)) == 0)
return(0); /* Gotta have a match */
case STAR: /* Zero or more ... */
are = l; /* Remember line start */
while ( (*l != 0) && ((e = pmatch(l, p)) != 0) )
l = e; /* Get longest match */
while (*p++ != ENDPAT); /* Skip over pattern */
while (l >= are) { /* Try to match rest */
if ( (e = pmatch(l, p)) != 0)
return(e);
--l; /* Nope, try earlier */
}
return(0); /* Nothing else worked */
default:
printf("Bad op code %d\n", op);
error("Cannot happen -- match\n");
}
}
return(l);
}
/*******************************************************/
void error(s)
char *s;
{
fprintf(stderr, "%s", s);
exit(1);
}
/*******************************************************/